#ifndef _CONE_SAMPLING_H
#define _CONE_SAMPLING_H

#include "circuitgraph.h"
#include "graphModel.h"
#include "extendedtimingparser.h"
#include "extendedlibparser.h"
#include "parser_helper.h"
#include <pthread.h>

#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/astar_search.hpp>
#include <boost/config.hpp>      

typedef void (*updFunctionPtr) (CircuitGraph&);

typedef struct pathBlossum_
{
        double root_violation;
        vertex_descriptor root_node;
        vector<vertex_descriptor> common_gates;
        vector< vector<vertex_descriptor> > critical_paths;
        
}pathBlossum;

typedef struct node_rank_
{
        int feasible_time;
        int cell_combination;
        double total_violation;
        double total_leakage;
        
}node_rank;

typedef struct cone_
{
        int done;
        double total_timing_viol;
        vertex_descriptor gate_idx;

        vector<vertex_descriptor> critical_path;
        vector<vertex_descriptor> gate_ids;
        vector<vertex_descriptor> critical_gates;
        
}cone;

typedef struct big_cone_
{
        int done;
        int merged;
        double most_violation;
        double total_timing_viol;

        vector<int> cone_ids;
        vector<vertex_descriptor> critical_gates;
        vector<vertex_descriptor> common_gates;

}big_cone;

class Cone{
        
  public:
  Cone() : Sample_Times(10), Fixed_Gates_Per_Itr(3), ReducedCellSize(4){}
        bool number_dffs(CircuitGraph&);
        bool topo_order_whole_graph(CircuitGraph&);
        bool topo_order_dffs(CircuitGraph&);
        bool form_cones(CircuitGraph&);
        bool reset_cones();
        void heuristic_sizing(CircuitGraph& GraphIn);
        bool clear_flag(CircuitGraph& GraphIn);
        bool add_cone(cone myCone){cones.push_back(myCone); return true;}
        bool del_cone(int cone_id){cones.erase(cones.begin() + cone_id); return true;}
        bool extract_critical_path(vertex_descriptor &vi, int cone_id, CircuitGraph& GraphIn);
        bool sampling(CircuitGraph& GraphIn, int coarse);
        bool sample_procedure(CircuitGraph& GraphIn, const int big_cone_id, const int NSamples, const int coarse);
        void normal_cone_sorting();
        void hybrid_cone_sorting();
        bool form_hybrid_cones(CircuitGraph& GraphIn);
        bool update_DFF_timing(CircuitGraph& GraphIn);
        int find_samples_per_gate(CircuitGraph& GraphIn, vertex_descriptor& vi, const int big_cone_id, const int NSamples, const bool critical, const int coarse);
        void find_critical_gates_Hybcone(CircuitGraph& GraphIn, const int big_cone_id, const int coarse);
        int finer_tuning(CircuitGraph& GraphIn);
        int finer_tuning2(CircuitGraph& GraphIn);
        void heuristic2(CircuitGraph& GraphIn);
        void heuristic3(CircuitGraph& GraphIn);
        void heuristic4(CircuitGraph& GraphIn);
        bool critical_gates_per_path(CircuitGraph& GraphIn, vector<vertex_descriptor>& path, vector<vertex_descriptor>& critical_gates);
        void single_gate_fixing(CircuitGraph& GraphIn, vertex_descriptor &in, vector<vertex_descriptor>& critical_gates);
        int find_samples_per_gate2(CircuitGraph& GraphIn, vertex_descriptor& vi, const double root_violation, const bool critical);
        int leakage_tuning(CircuitGraph& GraphIn);
        int upSizePercent(CircuitGraph& GraphIn);
        
  public:
        int level;
        int Sample_Times;
        int Fixed_Gates_Per_Itr;
        int ReducedCellSize;
        ExtendedTimingParser* TpPtr;
        ExtendedLibParser* LpPtr;
        vector<vertex_descriptor> worklist;
        vector<cone> cones;
        vector<big_cone> big_cones;
        updFunctionPtr updaterFunction ;
        
};

//#include "coneSampling.hpp"
#endif
